#ifndef MLOADER_VARIABLE
#define MLOADER_VARIABLE

#include "Common.h"

namespace MLoader
{
    class Texture2D;
    class Variable
    {
    public:
        Variable():data(nullptr), size(0) { }
        Variable(const Variable& val)
        {
            size = val.size;
            data = malloc(size);
            memcpy(data, val.data, size);
        }
        ~Variable()
        {
            if (data)
            {
                free(data);
                data = nullptr;
            }
        }

        Variable(const int& val)
        {
            size = sizeof(int);
            data = malloc(size);
            memcpy(data, &val, size);
        }
        Variable(const float& val)
        {
            size = sizeof(float);
            data = malloc(size);
            memcpy(data, &val, size);
        }
        Variable(const double& val)
        {
            size = sizeof(double);
            data = malloc(size);
            memcpy(data, &val, size);
        }
        Variable(const std::string& val)
        {
            size = val.size();
            data = malloc(size);
            memcpy(data, val.data(), size);
        }
        Variable(const gm::Vec2& val)
        {
            size = 2 * sizeof(float);
            data = malloc(size);
            memcpy(data, &(val[0]), size);
        }
        Variable(const gm::Vec3& val)
        {
            size = 3 * sizeof(float);
            data = malloc(size);
            memcpy(data, &(val[0]), size);
        }
        Variable(const gm::Vec4& val)
        {
            size = 4 * sizeof(float);
            data = malloc(size);
            memcpy(data, &(val[0]), size);
        }
        Variable(const gm::Transform2D& tranform)
        {
            size = sizeof(tranform);
            data = malloc(size);
            memcpy(data, &tranform, size);
        }
        Variable(Texture2D* tex)
        {
            size = sizeof(data);
            data = static_cast<void*>(tex);
        }
        
        int& ToInt()
        {
            return ((int*)data)[0];
        }
        float& Tofloat()
        {
            return ((float*)data)[0];
        }
        double& ToDouble()
        {
            return ((double*)data)[0];
        }
        std::string ToString()
        {
            return static_cast<char*>(data);
        }
        gm::Vec2 ToVec2()
        {
            float* val = (float *)data;
            return gm::Vec2(val[0], val[1]);
        }
        gm::Vec3 ToVec3()
        {
             float* val = (float *)data;
             return gm::Vec3(val[0], val[1], val[2]);
        }
        gm::Vec4 ToVec4()
        {
            float* val = (float *)data;
            return gm::Vec4(val[0], val[1], val[2], val[3]);
        }
        gm::Transform2D ToTransform2D()
        {
            gm::Transform2D transform;
            memcpy(&transform, data, sizeof(transform));
            return transform;
        }
        Texture2D* ToTexture2D()
        {
            return static_cast<Texture2D*>(data);
        }

    private:
        void* data;
        int size; // size of bits
    };
}


#endif // MLOADER_VARIABLE
